//
// Created by F1997 on 2025/2/10.
//

#ifndef CPPSTUDYPROJECTV3_SPMCQUEUETEMPLATE_H
#define CPPSTUDYPROJECTV3_SPMCQUEUETEMPLATE_H

#include <atomic>

/* 使用原子操作实现的无锁队列 */

template<class T, uint32_t CNT>
class SPMCQueue
{
public:
    static_assert(CNT && !(CNT & (CNT - 1)), "CNT must be a power of 2");
    struct Reader
    {
        operator bool() const { return q; }
        T* read() {
            auto& blk = q->blks[next_idx % CNT];
            uint32_t new_idx = ((std::atomic<uint32_t>*)&blk.idx)->load(std::memory_order_acquire);
            //std::cout << "read: " << blk.data << ":" << &blk.data << std::endl;
            if (int(new_idx - next_idx) < 0) return nullptr;
            next_idx = new_idx + 1;
            return &blk.data;
        }

        T* readLast() {
            T* ret = nullptr;
            while (T* cur = read()) ret = cur;
            return ret;
        }

        SPMCQueue<T, CNT>* q = nullptr;
        uint32_t next_idx;
    };

    Reader getReader() {
        Reader reader;
        reader.q = this;
        reader.next_idx = write_idx + 1;
        return reader;
    }

    template<typename Writer>
    void write(Writer writer) { // write接收一个可调用对象，writer是可调用对象，用了处理传入的数据
        auto& blk = blks[++write_idx % CNT];
        writer(blk.data);
        ((std::atomic<uint32_t>*)&blk.idx)->store(write_idx, std::memory_order_release);
    }

    // 重载 write 函数，使其接受 MarketData 类型的参数，并在内部处理该对象
    void write(const T& marketData) {
        auto& blk = blks[++write_idx % CNT];
        memcpy(blk.data, &marketData, sizeof(T));
        ((std::atomic<uint32_t>*)&blk.idx)->store(write_idx, std::memory_order_release);
    }

private:
    friend class Reader;
    struct alignas(64) Block
    {
        uint32_t idx = 0;
        T data;
    } blks[CNT];

    alignas(128) uint32_t write_idx = 0;
};


#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
// 自定义结构体
struct Message {
    int id;
    std::string content;

    // 为了方便结构体的输出，重载 << 操作符
    friend std::ostream& operator<<(std::ostream& os, const Message& msg) {
        return os << "ID: " << msg.id << ", Content: " << msg.content;
    }
};


// 生产者函数
template<class T, uint32_t CNT>
void producer(SPMCQueue<T, CNT>& queue) {
    for (int i = 0; i < 10; ++i) {
        // 每次生产一个整数，并通过 lambda 表达式将其赋值给队列中的元素
        queue.write([i](T& data) {
            data.id = i;
            data.content = "Message " + std::to_string(i);
            std::cout << "Produced: " << data << std::endl;
        });
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟生产延迟
    }
}

// 消费者函数
template<class T, uint32_t CNT>
void consumer(SPMCQueue<T, CNT>& queue) {
    auto reader = queue.getReader();
    while (true) {
        if (T* data = reader.read()) {
            std::cout << "Consumed: " << *data << std::endl;
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟消费延迟
        }
    }
}

#endif //CPPSTUDYPROJECTV3_SPMCQUEUETEMPLATE_H
